package com.mini.es.service;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.google.common.base.Joiner;
import com.mini.es.model.EsMiniStatisticPageParamNewModel;
import com.mini.es.repository.EsMiniStatisticDataNewRepository;
import com.mini.mysql.model.*;
import com.mini.mysql.repository.*;
import com.mini.mysql.service.MnsService;
import com.mini.util.StringUtil;
import com.mini.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchPhaseExecutionException;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.LongTerms;
import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.sum.Sum;
import org.elasticsearch.search.aggregations.metrics.valuecount.InternalValueCount;
import org.elasticsearch.search.aggregations.metrics.valuecount.ValueCount;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.StopWatch;

import javax.persistence.EntityManager;
import java.util.*;
import java.util.stream.Collectors;

import static com.mini.es.model.EsMiniStatisticPageParamNewModel.Fields.*;
import static org.elasticsearch.search.aggregations.AggregationBuilders.sum;

/**
 * 项目名称：mini-data-es
 * 类 名 称：EsMiniStatisticDataNewServiceImpl
 * 类 描 述：TODO
 * 创建时间：2021/3/31 下午6:04
 * 创 建 人：zhanghuiying
 */
@Slf4j
@Service
public class EsMiniStatisticDataNewServiceImpl implements EsMiniStatisticDataNewService {

    @Autowired
    private EsMiniStatisticDataNewRepository esMiniStatisticDataNewRepository;
    @Autowired
    private MnsService mnsService;
    @Autowired
    private UserFieldsServiceImpl userFieldsService;
    @Autowired
    EntityManager entityManager;
    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;
    @Autowired
    private BusinessPlanSitePageRRepository businessPlanSitePageRRepository;
    @Autowired
    private BusinessBaseSubInfoRepository businessBaseSubInfoRepository;
    @Autowired
    private BusinessBaseInfoRepository businessBaseInfoRepository;
    @Autowired
    private BusinessLessonSkuAppInfoRepository businessLessonSkuAppInfoRepository;
    @Autowired
    private BusinessPlanInfoRepository businessPlanInfoRepository;

    @Override
    public Iterable<EsMiniStatisticPageParamNewModel> save(List<EsMiniStatisticPageParamNewModel> list) {
        if (Objects.isNull(list) || list.isEmpty()) {
            return null;
        }
        Date now = new Date();
        return esMiniStatisticDataNewRepository.saveAll(list);
    }

    @Override
    public EsMiniStatisticPageParamNewModel findLatestUpdateTimeData() {
        Pageable pageable = PageRequest.of(1, 1, Sort.Direction.DESC, updateTime);
        try {
            Page<EsMiniStatisticPageParamNewModel> page = esMiniStatisticDataNewRepository.findAll(pageable);
            return page.getContent().isEmpty() ? null : page.getContent().get(0);
        } catch (SearchPhaseExecutionException e) {
            log.error("", e);
        }
        return null;
    }

    @Override
    public List<EsMiniStatisticPageParamNewModel> findAllById(List<Long> ids) {
        ArrayList<EsMiniStatisticPageParamNewModel> list = Lists.newArrayList();
        esMiniStatisticDataNewRepository.findAllById(ids).forEach(list::add);
        return list;
    }

    @Override
    public PageResultVO<MiniStatisticDataAllVO> pageListLevel1(MiniStatisticPageParamNew param) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start("拿到该用户下可查询的负责人id");
        //拿到该用户下可查询的负责人id
        Set<Long> userIds = scopedAdvertisingUserIds(param.getUserId());
        stopWatch.stop();
        stopWatch.start("负责人统计");
        if (StringUtils.isBlank(param.getRespId())) {
            param.setRespId(Joiner.on(",").join(userIds));
        } else {
            String[] arr = param.getRespId().replaceAll(" ", "").split(",");
            Set<Long> selectIds = new HashSet<>();
            for (int i = 0; i < arr.length; i++) {
                selectIds.add(Long.valueOf(arr[i]));
            }

            selectIds.retainAll(userIds);

            if (selectIds.isEmpty()) {
                param.setRespId("0");
            } else {
                param.setRespId(Joiner.on(",").join(selectIds));
            }
        }
        stopWatch.stop();

        //将用户自定义列放入redis
        if (StringUtil.notEmpty(param.getFields()) && !"ALL".equals(param.getFields())) {
            userFieldsService.SetUserQueryFields(param.getUserId(), param.getFields());
        }

        stopWatch.start("模糊查询，匹配mini_lesson_id");
        //模糊查询，匹配mini_lesson_id
        List<BusinessBaseSubInfo> infos = null;
        List<PlanInfo> planlist = new ArrayList<>();
        if (StringUtil.notEmpty(param.getKey())) {
            Long mini_lesson_id = null;
            try {
                mini_lesson_id = Long.parseLong(param.getKey());
            } catch (Exception e) {
                mini_lesson_id = null;
            }
            if (Objects.nonNull(mini_lesson_id)) {
                infos = businessBaseSubInfoRepository.findAllByParamAndMiniLessonId(param.getKey(), mini_lesson_id);
            } else {
                infos = businessBaseSubInfoRepository.findAllByParam(param.getKey());
            }

            List<Object[]> plans = businessPlanSitePageRRepository.selectByPlanListByKey(param.getKey());
            if (CollectionUtils.isNotEmpty(plans)) {
                for (Object[] p :
                        plans) {
                    String lessonSite = p[0] == null ? null : String.valueOf(p[0]);
                    String planSite = p[1] == null ? null : String.valueOf(p[1]);
                    String planName = p[2] == null ? null : String.valueOf(p[2]);
                    PlanInfo planInfo = new PlanInfo(lessonSite, planSite, planName);
                    planlist.add(planInfo);
                }
            }
        }

        if (!CollectionUtils.isEmpty(infos) || !CollectionUtils.isEmpty(planlist)) {
            if (!CollectionUtils.isEmpty(planlist)) {

                for (PlanInfo planInfo : planlist) {
                    BusinessBaseSubInfo temp = new BusinessBaseSubInfo();
                    try {
                        temp.setMiniLessonId(Long.parseLong(planInfo.getLessonSite()));
                        infos.add(temp);
                    } catch (Exception e) {
                        log.error("miniLessonId={} is not long error", planInfo.getLessonSite());
                    }
                }
            }
            List<Long> miniLessonIds = infos.stream().map(o -> o.getMiniLessonId()).collect(Collectors.toList());

            param.setMiniLessonId(Joiner.on(",").join(miniLessonIds));

        }
        stopWatch.stop();

        //查询es中的数据
        String trem = "";
        if (Objects.nonNull(param.getDimension()) && !param.getDimension().equals("")) {
            if (param.getDimension().equals("sku_code")) {
                trem = skuCode;
            }
            if (param.getDimension().equals("resp_id")) {
                trem = respId;
            }
            if (param.getDimension().equals("mini_lesson_id")) {
                trem = miniLessonId;
            }
            if (param.getDimension().equals("plan_id")) {
                trem = planId;
            }
            if (param.getDimension().equals("idea")) {
                trem = idea;
            }
        }
        stopWatch.start("es 查询封装耗时");
        NativeSearchQuery query = buildGroupSearch(trem, param.getDateStart(), param.getDateEnd(), param);
        stopWatch.stop();
        String finalTrem = trem;
        stopWatch.start("es 查询耗时");
        List<MiniStatisticDataAllVO> miniStatisticDataAllVOS = elasticsearchTemplate.query(query, resp -> {
            StopWatch time = new StopWatch();
            List<LongTerms.Bucket> longBuckets = null;
            List<StringTerms.Bucket> stringBuckets = null;
            List<MiniStatisticDataAllVO> list = new ArrayList<>();
            time.start("查询es中的数据");
            StringTerms stringTerms = resp.getAggregations().get(finalTrem);
            stringBuckets = stringTerms.getBuckets();

            time.stop();
            time.start("es查询结果赋值耗时2");
            for (StringTerms.Bucket bucket : stringBuckets) {
                Aggregations a = bucket.getAggregations();
                MiniStatisticDataAllVO summary = buildResult(null, bucket, a, finalTrem);
                summary.setTotal(0);
                list.add(summary);
            }
            time.stop();
            log.info(time.prettyPrint());
            return list;
        });
        stopWatch.stop();

        stopWatch.start("排序处理");
        //排序处理
        if (Objects.isNull(param.getSortType()) || param.getSortType().equals("asc")) {
            miniStatisticDataAllVOS = MiniStatisticDataAllVO.sortedAsc(miniStatisticDataAllVOS, param.getSortColumn());
        }
        if (Objects.nonNull(param.getSortType()) && param.getSortType().equals("desc")) {
            miniStatisticDataAllVOS = MiniStatisticDataAllVO.sortedDesc(miniStatisticDataAllVOS, param.getSortColumn());
        }
        stopWatch.stop();

        stopWatch.start("分页");
        //结果处理-ES中分组查询不能分页，这里手动分页
        List<MiniStatisticDataAllVO> rows = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(miniStatisticDataAllVOS) && param.getPageSize() != null) {
            int skip = param.getPageSize() * (param.getPageNumber() - 1);
            rows = miniStatisticDataAllVOS.stream().skip(skip).limit(param.getPageSize()).collect(Collectors.toList());
        }
        stopWatch.stop();

        stopWatch.start("结果赋值");
        String fields = userFieldsService.getUserQueryFields(param.getUserId());
        //结果补充赋值处理
        if (CollectionUtils.isNotEmpty(miniStatisticDataAllVOS) && Objects.nonNull(param.getDimension()) && param.getDimension().equals("mini_lesson_id")) {
            List<Long> collect = new ArrayList<>();
            List<MiniStatisticDataAllVO> dataNew = new ArrayList<>();
            if (param.getPageSize() != null) {
                collect = rows.stream().filter(o -> Objects.nonNull(o.getMiniLessonId())).map(MiniStatisticDataAllVO::getMiniLessonId).distinct().collect(Collectors.toList());
                dataNew = rows;
            } else {
                collect = miniStatisticDataAllVOS.stream().filter(o -> Objects.nonNull(o.getMiniLessonId())).map(MiniStatisticDataAllVO::getMiniLessonId).distinct().collect(Collectors.toList());
                dataNew = miniStatisticDataAllVOS;
            }
            List<BusinessBaseInfo> byIdIn = businessBaseInfoRepository.findByMiniLessonIdIn(collect);
            List<BusinessBaseSubInfo> baseSub = businessBaseSubInfoRepository.findBaseSub(collect);
            for (MiniStatisticDataAllVO data :
                    dataNew) {
                BusinessBaseInfo baseInfo = byIdIn.stream().filter(b -> b.getMiniLessonId().equals(data.getMiniLessonId()) && Objects.nonNull(b.getBusinessType())).findFirst().orElse(null);
                BusinessBaseSubInfo subInfo = baseSub.stream().filter(s -> s.getMiniLessonId().equals(data.getMiniLessonId())).findFirst().orElse(null);
                if (Objects.nonNull(baseInfo)) {
                    data.setLessonName(baseInfo.getLessonName());
                    data.setMiniLessonName(baseInfo.getMiniLessonName());
                    data.setChannelName(baseInfo.getChannelName());
                    data.setRespName(baseInfo.getFzName());
                    data.setGroupName(baseInfo.getGroupNames());
                    data.setWorkRoomName(baseInfo.getWorkRoomName());
                    data.setBusinessType(baseInfo.getBusinessType() == 0 ? "加盐" : "集团");
                    data.setPlanName(baseInfo.getPlanName());
                }
                if (Objects.nonNull(subInfo)) {
                    data.setSkuName(subInfo.getSkuName());
                    data.setPaySiteId(subInfo.getPaySiteId());
                    data.setUnPaySiteId(subInfo.getUnPaySiteId());
                    data.setGroupNames(subInfo.getGroupNames());
                }
                if (Objects.nonNull(param.getSkuCode()) && !param.getSkuCode().equals("-1")) {
                    data.setSkuCode(param.getSkuCode());
                }
                data.setFields(fields);
                data.setUnionId(UUID.randomUUID().toString());
                data.setPlanId("true");
            }
        }
        if (CollectionUtils.isNotEmpty(miniStatisticDataAllVOS) && Objects.nonNull(param.getDimension()) && param.getDimension().equals("resp_id")) {
            List<Long> collect = new ArrayList<>();
            List<MiniStatisticDataAllVO> dataNew = new ArrayList<>();
            if (param.getPageSize() != null) {
                collect = rows.stream().filter(r -> Objects.nonNull(r.getRespId())).map(MiniStatisticDataAllVO::getRespId).distinct().collect(Collectors.toList());
                dataNew = rows;
            } else {
                collect = miniStatisticDataAllVOS.stream().filter(r -> Objects.nonNull(r.getRespId())).map(MiniStatisticDataAllVO::getRespId).distinct().collect(Collectors.toList());
                dataNew = miniStatisticDataAllVOS;
            }
            List<UserVO> userSimpleInfos = mnsService.getUserSimpleInfos(collect);
            for (MiniStatisticDataAllVO data : dataNew) {
                UserVO userVO = userSimpleInfos.stream().filter(f -> f.getId().equals(data.getRespId())).findFirst().orElse(null);
                if (Objects.nonNull(userVO)) {
                    data.setRespName(userVO.getNickname());
                    data.setWorkRoomName(userVO.getFullDept().getWorkRoomName());
                }
                data.setFields(fields);
                data.setPlanId("true");
                data.setUnionId(UUID.randomUUID().toString());
                if (Objects.nonNull(param.getSkuCode()) && !param.getSkuCode().equals("-1")) {
                    data.setSkuCode(param.getSkuCode());
                }
            }
        }
        if (CollectionUtils.isNotEmpty(miniStatisticDataAllVOS) && Objects.nonNull(param.getDimension()) && param.getDimension().equals("sku_code")) {
            List<BusinessLessonSkuAppInfo> skuMap = businessLessonSkuAppInfoRepository.findAll();
            for (MiniStatisticDataAllVO data : rows) {
//                for (MiniStatisticDataAllVO data : miniStatisticDataAllVOS) {
                Optional<BusinessLessonSkuAppInfo> first = skuMap.stream().filter(s -> s.getSkuCode().equals(data.getSkuCode())).findFirst();
                if (first.isPresent()) {
                    data.setSkuName(first.get().getSkuName());
                } else {
                    data.setSkuName("集团");
                }
                data.setPlanId("true");
                data.setUnionId(UUID.randomUUID().toString());
            }
        }
        if (CollectionUtils.isNotEmpty(miniStatisticDataAllVOS) && Objects.nonNull(param.getDimension()) && param.getDimension().equals("plan_id")) {
            List<Integer> collect = miniStatisticDataAllVOS.stream().filter(r -> Objects.nonNull(r.getPlanId())).map(MiniStatisticDataAllVO::getPlanId).distinct().map(c -> Integer.valueOf(c)).collect(Collectors.toList());
            BusinessBaseInfo baseInfo = businessBaseInfoRepository.findByMiniLessonId(Long.valueOf(param.getMiniLessonId()));
            List<BusinessPlanInfo> planInfos = businessPlanInfoRepository.findByPlanSiteIn(collect);
            for (MiniStatisticDataAllVO data :
                    miniStatisticDataAllVOS) {
                Optional<BusinessPlanInfo> first = planInfos.stream().filter(s -> s.getPlanSite().toString().equals(data.getPlanId())).findFirst();
                if (first.isPresent()) {
                    data.setPlanName(first.get().getPlanName());
                }
                if (Objects.nonNull(baseInfo)) {
                    data.setLessonName(baseInfo.getLessonName());
                    data.setMiniLessonName(baseInfo.getMiniLessonName());
                    data.setChannelName(baseInfo.getChannelName());
                    data.setRespName(baseInfo.getFzName());
                    data.setGroupName(baseInfo.getGroupNames());
                    data.setWorkRoomName(baseInfo.getWorkRoomName());
                    data.setBusinessType(baseInfo.getBusinessType() == 0 ? "加盐" : "集团");
                }
                if (Objects.nonNull(param.getSkuCode()) && !param.getSkuCode().equals("-1")) {
                    data.setSkuCode(param.getSkuCode());
                }
                data.setMiniLessonId(Long.valueOf(param.getMiniLessonId()));
                data.setUnionId(UUID.randomUUID().toString());
            }
        }
        if (CollectionUtils.isNotEmpty(miniStatisticDataAllVOS) && Objects.nonNull(param.getDimension()) && param.getDimension().equals("idea")) {
            BusinessPlanInfo planInfo = businessPlanInfoRepository.findByPlanSite(param.getPlanId().equals("") ? 0 : Integer.valueOf(param.getPlanId()));
            BusinessBaseInfo baseInfo = businessBaseInfoRepository.findByMiniLessonId(param.getMiniLessonId().equals("") ? 0 : Long.valueOf(param.getMiniLessonId()));
            if (Objects.nonNull(planInfo) && Objects.nonNull(baseInfo)) {
                for (MiniStatisticDataAllVO data :
                        miniStatisticDataAllVOS) {
                    data.setMiniLessonId(Long.valueOf(param.getMiniLessonId()));
                    data.setPlanId(param.getPlanId());
                    data.setPlanName(planInfo.getPlanName());
                    data.setLessonName(baseInfo.getLessonName());
                    data.setMiniLessonName(baseInfo.getMiniLessonName());
                    data.setChannelName(baseInfo.getChannelName());
                    data.setRespName(baseInfo.getFzName());
                    data.setGroupName(baseInfo.getGroupNames());
                    data.setWorkRoomName(baseInfo.getWorkRoomName());
                    data.setBusinessType(baseInfo.getBusinessType() == 0 ? "加盐" : "集团");
                    data.setUnionId(UUID.randomUUID().toString());
                    if (data.getIdea().equals("-1")){
                        data.setIdea("");
                    }
                }
            }
        }
        stopWatch.stop();

//        stopWatch.start("分页");
//        //结果处理-ES中分组查询不能分页，这里手动分页
//        List<MiniStatisticDataAllVO> rows = new ArrayList<>();
//        if (param.getPageSize() != null) {
//            int skip = param.getPageSize() * (param.getPageNumber() - 1);
//            rows = miniStatisticDataAllVOS.stream().skip(skip).limit(param.getPageSize()).collect(Collectors.toList());
//        }
//        stopWatch.stop();

        //汇总数据，将汇总数据放到第一条
        PageResultVO<MiniStatisticDataAllVO> page = new PageResultVO<>();
        stopWatch.start("汇总数据");

        if (param.getPageSize() != null) {
            int count=miniStatisticDataAllVOS.size();
            count=count+((count % param.getPageSize()) > 0 ? (count / param.getPageSize() + 1) : (count / param.getPageSize()));
            if (CollectionUtils.isNotEmpty(rows)) {
                MiniStatisticDataAllVO sums = totalSummary(miniStatisticDataAllVOS);
                sums.setTotal(1);
                rows.add(0, sums);
            }

            page = new PageResultVO<>(count, rows);
        } else if (CollectionUtils.isNotEmpty(miniStatisticDataAllVOS)) {
            page = new PageResultVO<>(miniStatisticDataAllVOS.size(), miniStatisticDataAllVOS);
        }
        stopWatch.stop();
        log.info(stopWatch.prettyPrint());
        return page;
    }

    public Set<Long> scopedAdvertisingUserIds(Long userId) {
        return mnsService.scopedAdvertisingUserIds(userId);
    }

    public NativeSearchQuery buildGroupSearch(String trem, String startTime, String endTime, MiniStatisticPageParamNew param) {
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        //构建分组
        TermsAggregationBuilder aggBuilder = AggregationBuilders
                .terms(trem).field(trem)
                .executionHint("map")
                .subAggregation(sum(MiniStatisticDataAllVO.Fields.pv).field(EsMiniStatisticPageParamNewModel.Fields.pv))
                .subAggregation(sum(MiniStatisticDataAllVO.Fields.uv).field(EsMiniStatisticPageParamNewModel.Fields.uv))
                .subAggregation(sum(MiniStatisticDataAllVO.Fields.cash).field(EsMiniStatisticPageParamNewModel.Fields.cash))
                .subAggregation(sum(MiniStatisticDataAllVO.Fields.cost).field(EsMiniStatisticPageParamNewModel.Fields.cost))
                .subAggregation(sum(MiniStatisticDataAllVO.Fields.click).field(EsMiniStatisticPageParamNewModel.Fields.click))
                .subAggregation(sum(MiniStatisticDataAllVO.Fields.showCount).field(EsMiniStatisticPageParamNewModel.Fields.showCount))
                .subAggregation(sum(MiniStatisticDataAllVO.Fields.formCardTotal).field(EsMiniStatisticPageParamNewModel.Fields.formCardTotal))
                .subAggregation(sum(MiniStatisticDataAllVO.Fields.payCardTotal).field(EsMiniStatisticPageParamNewModel.Fields.payCardTotal))
                .subAggregation(sum(MiniStatisticDataAllVO.Fields.chanceTotal).field(EsMiniStatisticPageParamNewModel.Fields.chanceTotal))
                .subAggregation(sum(MiniStatisticDataAllVO.Fields.courseMoney).field(EsMiniStatisticPageParamNewModel.Fields.courseMoney))
                .subAggregation(sum(MiniStatisticDataAllVO.Fields.addWxTotal).field(EsMiniStatisticPageParamNewModel.Fields.addWxTotal))
                .subAggregation(sum(MiniStatisticDataAllVO.Fields.bigCourseMoney).field(EsMiniStatisticPageParamNewModel.Fields.bigCourseMoney))
                .subAggregation(sum(MiniStatisticDataAllVO.Fields.appRegisterNum).field(EsMiniStatisticPageParamNewModel.Fields.appRegisterNum))
                .subAggregation(sum(MiniStatisticDataAllVO.Fields.smsSendNum).field(EsMiniStatisticPageParamNewModel.Fields.smsSendNum))
                .subAggregation(sum(MiniStatisticDataAllVO.Fields.getCouponNum).field(EsMiniStatisticPageParamNewModel.Fields.getCouponNum))
                .subAggregation(sum(MiniStatisticDataAllVO.Fields.bigCourseOrderCount).field(EsMiniStatisticPageParamNewModel.Fields.bigCourseOrderCount))
                .subAggregation(sum(MiniStatisticDataAllVO.Fields.youzanMoney).field(EsMiniStatisticPageParamNewModel.Fields.youzanMoney))
                .subAggregation(sum(MiniStatisticDataAllVO.Fields.youzanMoneyAll).field(EsMiniStatisticPageParamNewModel.Fields.youzanMoneyAll))
                .subAggregation(sum(MiniStatisticDataAllVO.Fields.companyMoney).field(EsMiniStatisticPageParamNewModel.Fields.companyMoney))
                .subAggregation(sum(MiniStatisticDataAllVO.Fields.companyRefund).field(EsMiniStatisticPageParamNewModel.Fields.companyRefund))
                .subAggregation(sum(MiniStatisticDataAllVO.Fields.youzanRefund).field(EsMiniStatisticPageParamNewModel.Fields.youzanRefund))
                .subAggregation(sum(MiniStatisticDataAllVO.Fields.liveSellCount).field(EsMiniStatisticPageParamNewModel.Fields.liveSellCount))
                .subAggregation(sum(MiniStatisticDataAllVO.Fields.liveSellCountAll).field(EsMiniStatisticPageParamNewModel.Fields.liveSellCountAll))
                .subAggregation(sum(MiniStatisticDataAllVO.Fields.liveSellMoney).field(EsMiniStatisticPageParamNewModel.Fields.liveSellMoney))
                .subAggregation(sum(MiniStatisticDataAllVO.Fields.liveSellMoneyAll).field(EsMiniStatisticPageParamNewModel.Fields.liveSellMoneyAll))
                .subAggregation(sum(MiniStatisticDataAllVO.Fields.xcxMoney).field(EsMiniStatisticPageParamNewModel.Fields.xcxMoney))
                .subAggregation(sum(MiniStatisticDataAllVO.Fields.xcxMoneyAll).field(EsMiniStatisticPageParamNewModel.Fields.xcxMoneyAll))
                .subAggregation(sum(MiniStatisticDataAllVO.Fields.xcxRefund).field(EsMiniStatisticPageParamNewModel.Fields.xcxRefund))
                .subAggregation(sum(MiniStatisticDataAllVO.Fields.xcxRefundCount).field(EsMiniStatisticPageParamNewModel.Fields.xcxRefundCount))
                .subAggregation(sum(MiniStatisticDataAllVO.Fields.youzanRefundCount).field(EsMiniStatisticPageParamNewModel.Fields.youzanRefundCount))
                .subAggregation(sum(MiniStatisticDataAllVO.Fields.companyRefundCount).field(EsMiniStatisticPageParamNewModel.Fields.companyRefundCount))
                .size(Integer.MAX_VALUE);
        builder.addAggregation(aggBuilder);

        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        //加入时间范围搜索
        if (StringUtils.isNotBlank(startTime) && StringUtils.isNotBlank(endTime)) {
            Date s = DateUtil.parse(startTime, DatePattern.NORM_DATE_FORMAT);
            Date e = DateUtil.parse(endTime, DatePattern.NORM_DATE_FORMAT);
            RangeQueryBuilder rangequerybuilder = QueryBuilders
                    .rangeQuery(EsMiniStatisticPageParamNewModel.Fields.miniDate)
                    .from(s.getTime())
                    .to(e.getTime());
            boolQueryBuilder.must(rangequerybuilder);
        }

        if (Objects.nonNull(param.getRespId())) {
            List<String> respIds = Arrays.asList(param.getRespId().split(","));
            if (CollectionUtils.isNotEmpty(respIds)) {
                BoolQueryBuilder boolQueryBuilder1 = QueryBuilders.boolQuery();
                for (String id :
                        respIds) {
                    boolQueryBuilder1.should(QueryBuilders.termQuery(respId, id));
                }

                boolQueryBuilder.must(boolQueryBuilder1);
            }
        }

        if (Objects.nonNull(param.getMiniLessonId())) {
            List<String> miniLessonIds = Arrays.asList(param.getMiniLessonId().split(","));
            if (CollectionUtils.isNotEmpty(miniLessonIds)) {
                BoolQueryBuilder boolQueryBuilder2 = QueryBuilders.boolQuery();
                for (String lessonId :
                        miniLessonIds) {
                    boolQueryBuilder2.should(QueryBuilders.termQuery(miniLessonId, lessonId));
                }
                boolQueryBuilder.must(boolQueryBuilder2);
            }
        }

        if (Objects.nonNull(param.getChannelCode()) && !param.getChannelCode().equals("")) {
            boolQueryBuilder.must(QueryBuilders.matchPhraseQuery(channelCode, param.getChannelCode()));
        }

        if (Objects.nonNull(param.getLessonId()) && !param.getLessonId().equals("")) {
            boolQueryBuilder.must(QueryBuilders.matchPhraseQuery(lessonId, param.getLessonId()));
        }
        if (Objects.nonNull(param.getPlanId())) {
            boolQueryBuilder.must(QueryBuilders.matchPhraseQuery(planId, param.getPlanId()));
        }

        if (Objects.nonNull(param.getSkuCode()) && !param.getSkuCode().equals("") && !param.getSkuCode().equals("-1")) {
            boolQueryBuilder.must(QueryBuilders.matchPhraseQuery(EsMiniStatisticPageParamNewModel.Fields.skuCode, param.getSkuCode()));
            boolQueryBuilder.must(QueryBuilders.existsQuery(EsMiniStatisticPageParamNewModel.Fields.skuCode));
        }
        if (Objects.nonNull(param.getSkuCode()) && param.getSkuCode().equals("-1")) {
            boolQueryBuilder.must(QueryBuilders.matchPhraseQuery(EsMiniStatisticPageParamNewModel.Fields.skuCode, ""));
        }

        if (CollectionUtils.isNotEmpty(param.getDeptIds())) {
            BoolQueryBuilder boolQueryBuilder2 = QueryBuilders.boolQuery();
            for (Long deptid :
                    param.getDeptIds()) {
                boolQueryBuilder2.should(QueryBuilders.matchPhraseQuery(workRoomId, deptid));
            }
            boolQueryBuilder.must(boolQueryBuilder2);
        }

        builder.withQuery(boolQueryBuilder);
        builder.withIndices(EsMiniStatisticPageParamNewModel.index);
        return builder.build();
    }

    public MiniStatisticDataAllVO buildResult(LongTerms.Bucket longBucket, StringTerms.Bucket stringBucket, Aggregations a, String trem) {
        return MiniStatisticDataAllVO.builder()
                .respId(trem.equals(respId) ? Long.valueOf(stringBucket.getKeyAsString()) : null)
                .miniLessonId(trem.equals(miniLessonId) ? Long.valueOf(stringBucket.getKeyAsString()) : null)
                .skuCode(trem.equals(skuCode) ? stringBucket.getKeyAsString() : null)
                .planId(trem.equals(planId) ? stringBucket.getKeyAsString() : null)
                .idea(trem.equals(idea) ? stringBucket.getKeyAsString() : null)
                .pv((long) getDoubleValue(a, EsMiniStatisticPageParamNewModel.Fields.pv))
                .uv((long) getDoubleValue(a, EsMiniStatisticPageParamNewModel.Fields.uv))
                .cash(getDoubleValue(a, EsMiniStatisticPageParamNewModel.Fields.cash))
                .cost(getDoubleValue(a, EsMiniStatisticPageParamNewModel.Fields.cost))
                .click((long) getDoubleValue(a, EsMiniStatisticPageParamNewModel.Fields.click))
                .showCount((long) getDoubleValue(a, showCount))
                .formCardTotal((long) getDoubleValue(a, EsMiniStatisticPageParamNewModel.Fields.formCardTotal))
                .payCardTotal((long) getDoubleValue(a, payCardTotal))
                .chanceTotal((long) getDoubleValue(a, EsMiniStatisticPageParamNewModel.Fields.chanceTotal))
                .courseMoney(getDoubleValue(a, EsMiniStatisticPageParamNewModel.Fields.courseMoney))
                .addWxTotal((long) getDoubleValue(a, EsMiniStatisticPageParamNewModel.Fields.addWxTotal))
                .bigCourseMoney(getDoubleValue(a, EsMiniStatisticPageParamNewModel.Fields.bigCourseMoney))
                .appRegisterNum((long) getDoubleValue(a, EsMiniStatisticPageParamNewModel.Fields.appRegisterNum))
                .smsSendNum((long) getDoubleValue(a, smsSendNum))
                .getCouponNum((long) getDoubleValue(a, EsMiniStatisticPageParamNewModel.Fields.getCouponNum))
                .bigCourseOrderCount((long) getDoubleValue(a, EsMiniStatisticPageParamNewModel.Fields.bigCourseOrderCount))
                .youzanMoney(getDoubleValue(a, youzanMoney))
                .youzanMoneyAll(getDoubleValue(a, youzanMoneyAll))
                .companyMoney(getDoubleValue(a, companyMoney))
                .companyRefund(getDoubleValue(a, companyRefund))
                .youzanRefund(getDoubleValue(a, youzanRefund))
                .liveSellCount((long) getDoubleValue(a, liveSellCount))
                .liveSellCountAll((long) getDoubleValue(a, liveSellCountAll))
                .liveSellMoney(getDoubleValue(a, liveSellMoney))
                .liveSellMoneyAll(getDoubleValue(a, liveSellMoneyAll))
                .xcxMoney(getDoubleValue(a, xcxMoney))
                .xcxMoneyAll(getDoubleValue(a, xcxMoneyAll))
                .xcxRefund(getDoubleValue(a, xcxRefund))
                .xcxRefundCount((long) getDoubleValue(a, xcxRefundCount))
                .youzanRefundCount((long) getDoubleValue(a, youzanRefundCount))
                .companyRefundCount((long) getDoubleValue(a, companyRefundCount))
                .build();
    }

    public static double getDoubleValue(Aggregations a, String field) {
        Object result = common(a, field);
        return Double.parseDouble(String.valueOf(result));
    }

    public static int getIntegerValue(Aggregations a, String field) {
        Object result = common(a, field);
        return Integer.parseInt(String.valueOf(result));
    }

    //对返回值类型进行处理
    public static Object common(Aggregations a, String field) {
        Aggregation aggregation = a.get(field);
        Object result = null;
        if (aggregation instanceof Sum) {
            result = ((Sum) a.get(field)).getValueAsString();
        } else if (aggregation instanceof ValueCount) {
            result = ((InternalValueCount) a.get(field)).getValue();
        } else {
            try {
                throw new Exception("未处理的结果类型 " + aggregation.getType());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    public static MiniStatisticDataAllVO totalSummary(List<MiniStatisticDataAllVO> allVOList) {
        return CollectionUtils.isEmpty(allVOList) ? null : MiniStatisticDataAllVO.builder()
                .pv(allVOList.stream().map(MiniStatisticDataAllVO::getPv).filter(Objects::nonNull).reduce(Long::sum).orElse(null))
                .uv(allVOList.stream().map(MiniStatisticDataAllVO::getUv).filter(Objects::nonNull).reduce(Long::sum).orElse(null))
                .cash(allVOList.stream().map(MiniStatisticDataAllVO::getCash).filter(Objects::nonNull).reduce(Double::sum).orElse(null))
                .cost(allVOList.stream().map(MiniStatisticDataAllVO::getCost).filter(Objects::nonNull).reduce(Double::sum).orElse(null))
                .click(allVOList.stream().map(MiniStatisticDataAllVO::getClick).filter(Objects::nonNull).reduce(Long::sum).orElse(null))
                .showCount(allVOList.stream().map(MiniStatisticDataAllVO::getShowCount).filter(Objects::nonNull).reduce(Long::sum).orElse(null))
                .formCardTotal(allVOList.stream().map(MiniStatisticDataAllVO::getFormCardTotal).filter(Objects::nonNull).reduce(Long::sum).orElse(null))
                .payCardTotal(allVOList.stream().map(MiniStatisticDataAllVO::getPayCardTotal).filter(Objects::nonNull).reduce(Long::sum).orElse(null))
                .chanceTotal(allVOList.stream().map(MiniStatisticDataAllVO::getChanceTotal).filter(Objects::nonNull).reduce(Long::sum).orElse(null))
                .courseMoney(allVOList.stream().map(MiniStatisticDataAllVO::getCourseMoney).filter(Objects::nonNull).reduce(Double::sum).orElse(null))
                .addWxTotal(allVOList.stream().map(MiniStatisticDataAllVO::getAddWxTotal).filter(Objects::nonNull).reduce(Long::sum).orElse(null))
                .bigCourseMoney(allVOList.stream().map(MiniStatisticDataAllVO::getBigCourseMoney).filter(Objects::nonNull).reduce(Double::sum).orElse(null))
                .appRegisterNum(allVOList.stream().map(MiniStatisticDataAllVO::getAppRegisterNum).filter(Objects::nonNull).reduce(Long::sum).orElse(null))
                .smsSendNum(allVOList.stream().map(MiniStatisticDataAllVO::getSmsSendNum).filter(Objects::nonNull).reduce(Long::sum).orElse(null))
                .getCouponNum(allVOList.stream().map(MiniStatisticDataAllVO::getGetCouponNum).filter(Objects::nonNull).reduce(Long::sum).orElse(null))
                .bigCourseOrderCount(allVOList.stream().map(MiniStatisticDataAllVO::getBigCourseOrderCount).filter(Objects::nonNull).reduce(Long::sum).orElse(null))
                .youzanMoney(allVOList.stream().map(MiniStatisticDataAllVO::getYouzanMoney).filter(Objects::nonNull).reduce(Double::sum).orElse(null))
                .youzanMoneyAll(allVOList.stream().map(MiniStatisticDataAllVO::getYouzanMoneyAll).filter(Objects::nonNull).reduce(Double::sum).orElse(null))
                .companyMoney(allVOList.stream().map(MiniStatisticDataAllVO::getCompanyMoney).filter(Objects::nonNull).reduce(Double::sum).orElse(null))
                .companyRefund(allVOList.stream().map(MiniStatisticDataAllVO::getCompanyRefund).filter(Objects::nonNull).reduce(Double::sum).orElse(null))
                .youzanRefund(allVOList.stream().map(MiniStatisticDataAllVO::getYouzanRefund).filter(Objects::nonNull).reduce(Double::sum).orElse(null))
                .liveSellCount(allVOList.stream().map(MiniStatisticDataAllVO::getLiveSellCount).filter(Objects::nonNull).reduce(Long::sum).orElse(null))
                .liveSellCountAll(allVOList.stream().map(MiniStatisticDataAllVO::getLiveSellCountAll).filter(Objects::nonNull).reduce(Long::sum).orElse(null))
                .liveSellMoney(allVOList.stream().map(MiniStatisticDataAllVO::getLiveSellMoney).filter(Objects::nonNull).reduce(Double::sum).orElse(null))
                .liveSellMoneyAll(allVOList.stream().map(MiniStatisticDataAllVO::getLiveSellMoneyAll).filter(Objects::nonNull).reduce(Double::sum).orElse(null))
                .xcxMoney(allVOList.stream().map(MiniStatisticDataAllVO::getXcxMoney).filter(Objects::nonNull).reduce(Double::sum).orElse(null))
                .xcxMoneyAll(allVOList.stream().map(MiniStatisticDataAllVO::getXcxMoneyAll).filter(Objects::nonNull).reduce(Double::sum).orElse(null))
                .xcxRefund(allVOList.stream().map(MiniStatisticDataAllVO::getXcxRefund).filter(Objects::nonNull).reduce(Double::sum).orElse(null))
                .xcxRefundCount(allVOList.stream().map(MiniStatisticDataAllVO::getXcxRefundCount).filter(Objects::nonNull).reduce(Long::sum).orElse(null))
                .youzanRefundCount(allVOList.stream().map(MiniStatisticDataAllVO::getYouzanRefundCount).filter(Objects::nonNull).reduce(Long::sum).orElse(null))
                .companyRefundCount(allVOList.stream().map(MiniStatisticDataAllVO::getCompanyRefundCount).filter(Objects::nonNull).reduce(Long::sum).orElse(null))
                .build();
    }
}
